package org.yxing.palpalgps.image;

import java.io.InputStream;
import java.net.URL;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;

import org.yxing.palpalgps.PalPalGPSApplication;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

/**
 * load image
 * @author yuxing
 *
 */
public class ImageLoader {
	private static final String TAG = ImageLoader.class.getSimpleName();
	
	private static final int ON_START = 0;
	private static final int ON_FALL = 1;
	private static final int ON_END = 2;
	
	private static ImageCache sImageCache;
	private static ExecutorService sExecutorService;
	
	public ImageLoader(Context context) {
		PalPalGPSApplication application = null;
		if (sImageCache == null) {
			application = (PalPalGPSApplication) context.getApplicationContext();
			sImageCache = application.getImageCache();
		}
		if (sExecutorService == null) {
			if (application == null)
				application = (PalPalGPSApplication) context.getApplicationContext();
			sExecutorService = application.getExcutorService();
		}
	}
	
	public Future<?> loadImage(String url, ImageLoaderCallback callback) {
		return sExecutorService.submit(new ImageFetcher(url, callback));
	}
	
	private class ImageFetcher implements Runnable {
		
		private ImageHandler mHandler;
		private String mUrl;

		public ImageFetcher(String url, ImageLoaderCallback callback) {
			mHandler = new ImageHandler(callback);
			mUrl = url;
		}
		@Override
		public void run() {
			
			Throwable throwable = null;
			Bitmap bitmap = null;
			
			mHandler.sendMessage(Message.obtain(mHandler, ON_START));
			try {
				Log.v(TAG, "" + mUrl);
				URL url = new URL(mUrl);
				InputStream is = url.openStream();
				bitmap = BitmapFactory.decodeStream(is);
				
			} catch (Exception e) {
				throwable = e;
			}
			
			if (bitmap == null) {
				if (throwable == null)
					throwable = new Exception("Skia image decoding failed");
				mHandler.sendMessage(Message.obtain(mHandler, ON_FALL, throwable));
			} else {
				sImageCache.put(mUrl, bitmap);
				mHandler.sendMessage(Message.obtain(mHandler, ON_END, bitmap));
			}
		}
		
	}
	
	public static interface ImageLoaderCallback {
		void onImageLoderStarted(ImageLoader loader);
		void onImageLoderEnded(ImageLoader loader, Bitmap bitmap);
		void onImageLoaderFall(ImageLoader loader, Throwable exception);
	}
	
	private class ImageHandler extends Handler {
		
		private ImageLoaderCallback mCallback;
		
		public ImageHandler(ImageLoaderCallback callback) {
			mCallback = callback;
		}
		
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case ON_START:
				mCallback.onImageLoderStarted(ImageLoader.this);
				break;
			case ON_END:
				mCallback.onImageLoderEnded(ImageLoader.this, (Bitmap) msg.obj);
				break;
			case ON_FALL:
				mCallback.onImageLoaderFall(ImageLoader.this, (Throwable)msg.obj);
				break;
			}
		}
	}
}
